/*******************************************************************************
  * @file                   stepper_s.1.c
  * @Author:                MQjehovah                 mail:MQjehovah@hotmail.com
  * @version                1.0.0
  * @date                   2018-02-28 14:15:45
  * @brief                  加速曲线是根据时间来离散的，所以每个阶段由时间来分割，及时间累积达到某个值。总的加速时间值由用户指定
  ******************************************************************************
  * @attention
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "stepper.h"
#include "shell.h"
/* Definition ----------------------------------------------------------------*/
STEPPER motor = {.id = 1, .dir_pos = 1, .div = 4, .TIMx = STEP_TIM};
STEPPER *pmotor = &motor;
u16 table_time[ACC_TIME_DIV] = {4187, 4117, 4042, 3963, 3880, 3791, 3698, 3601, 3500, 3394, 3286, 3173,
                                3058, 2941, 2822, 2702, 2581, 2461, 2341, 2222, 2104, 1990, 1878, 1769, 1663, 1562, 1465, 1372, 1284, 1200,
                                1121, 1047, 977, 912, 851, 794, 742, 693, 648, 606, 568, 532, 500, 470, 443, 418, 395, 374, 355, 338, 322, 308,
                                295, 283, 272, 262, 253, 245, 237, 231, 225, 219, 214, 210, 206, 202, 198, 195, 193, 190, 188, 186, 184, 182, 181,
                                179, 178, 177, 176, 175, 174, 173, 173, 172, 172, 171, 171, 170, 170, 169, 169, 169, 169, 168, 168, 168, 168, 168, 167, 167};

/* Functions -----------------------------------------------------------------*/
/*******************************************************************************
  * @brief  步进电机GPIO口初始化              
  * @param  None                   
  * @retval None                   
  * @Note   用户自己实现                   
*******************************************************************************/
void Motor_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE); //使能PORTA PORTB时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;                                    //PB4-EN
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                                //普通输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                               //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;                           //100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                                 //上拉
    GPIO_Init(GPIOB, &GPIO_InitStructure);                                       //初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                                    //PB3-PUL
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                                 //复用功能(如果是采用定时器PWM输出需要配制成AF模式)
    GPIO_Init(GPIOB, &GPIO_InitStructure);                                       //初始化PB3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                                   //PA10-DIR
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

#if 0 //高级定时器
/*******************************************************************************
  * @brief  高级定时器驱动S型电机驱动              
  * @param  None                   
  * @retval None                   
  * @Note   使用高级定时器1，使用TIM_RepetitionCounter参数跳过细分中断
            减少中断的次数       
*******************************************************************************/
void Initial_PWM_Motor1(void)
{
    TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    Motor_GPIO_Init();
    TIM_DeInit(TIM1);
    //中断NVIC设置：允许中断，设置优先级
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PWM1_PreemptionPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = PWM1_SubPriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    TIM_BaseInitStructure.TIM_Period = 1000-1;
    TIM_BaseInitStructure.TIM_Prescaler = 84-1;
    TIM_BaseInitStructure.TIM_ClockDivision = 0;
    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;               //PWM2模式
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //信号输出到对应的输出引脚
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补信号输出到对应的输出引脚
    TIM_OCInitStructure.TIM_Pulse = 500;                             //脉冲宽度
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;        //互补输出高电平有效
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;     //互补输出高电平有效
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;    //输出空闲状态为1
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;   //互补输出空闲状态为0
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);                        //OC1通道初始化

    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM1, ENABLE);

    //清中断，以免一启用中断后立即产生中断
    TIM_ClearFlag(TIM1, TIM_FLAG_Update);
    //使能TIM1中断源
    TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM1, DISABLE);
    TIM_CtrlPWMOutputs(TIM1, ENABLE); //使能PWM输出
}
#endif

/*******************************************************************************
  * @brief  电机驱动定时器初始化              
  * @param  None                   
  * @retval None                   
  * @Note   使用定时器TIM2，输出PWM，每次脉冲进入中断                
*******************************************************************************/
void Motor_PWM_Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_TIM2); //GPIOB3复用为定时器2
    Motor_GPIO_Init();
    TIM_DeInit(TIM2);
    //中断NVIC设置：允许中断，设置优先级
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;           //更新事件 	TIM2_IRQHandler
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;        //响应优先级1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //允许中断
    NVIC_Init(&NVIC_InitStructure);
    TIM_BaseInitStructure.TIM_Period = 160;
    TIM_BaseInitStructure.TIM_Prescaler = 84 - 1;
    TIM_BaseInitStructure.TIM_ClockDivision = 0;
    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_BaseInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;               //PWM2模式
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //信号输出到对应的输出引脚
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补信号输出到对应的输出引脚
    TIM_OCInitStructure.TIM_Pulse = 80;                             //脉冲宽度
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;        //互补输出高电平有效
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;     //互补输出高电平有效
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;    //输出空闲状态为1
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;   //互补输出空闲状态为0
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);                        //OC1通道初始化

    TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除溢出中断标志
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的预装载寄存器
    TIM_ARRPreloadConfig(TIM2, ENABLE);               //ARPE使能
    TIM_CCPreloadControl(TIM2, ENABLE);
    TIM_CtrlPWMOutputs(TIM2, ENABLE);
    //TIM_Cmd(TIM2, ENABLE); //使能TIM2
}

/*******************************************************************************
  * @brief  计算S型曲线表              
  * @param  None                   
  * @retval None                   
  * @Note   None                   
*******************************************************************************/
void Calculate_S_Table(void)
{
}

/*******************************************************************************
  * @brief  电机初始化函数              
  * @param  None                   
  * @retval None                   
  * @Note   None                   
*******************************************************************************/
void MOTOR_Init(void)
{
    Motor_PWM_Init(); //初始化电机驱动PWM
    /* 初始化电机参数 */
}

int test;
/*******************************************************************************
  * @brief  定时器2中断函数
  * @param  None                   
  * @retval None                   
  * @Note   None                   
*******************************************************************************/
void TIM2_IRQHandler(void)
{
    static int cnt = 0;
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
        if (1 == pmotor->en)//若电机使能
        {
            //位置计算
            // if (pmotor->dir_pos == pmotor->dir)
            // {
            //     pmotor->current_puase++;
            // }
            // else
            // {
            //     pmotor->current_puase--;
            // }
            // pmotor->current_step = pmotor->current_puase / pmotor->div;
            pmotor->step_time += table_time[pmotor->f_index];
            if (cnt++ > pmotor->div) // 步进电机每走一步
            {
                cnt = 0;
                pmotor->passed_puase++; //总脉冲个数
                switch (pmotor->state)
                {
                case acc: //加速阶段
                    test = pmotor->step >> 1;
                    if (pmotor->passed_puase < test)
                    {
                        if (pmotor->step_time > TIME_PER_DIV * 1000) //一个频率的步数走完
                        {
                            pmotor->f_index++;
                            //判断加速阶段是否结束
                            if (pmotor->f_index > ACC_TIME_DIV - 2)
                            {
                                //规划平速运行阶段和减速运行阶段
                                pmotor->avg_step = pmotor->step - pmotor->passed_puase * 2;
                                pmotor->state = avg;
                            }
                            else
                            {
                                TIM2->ARR = table_time[pmotor->f_index];
                                test = table_time[pmotor->f_index] >> 1;
                                TIM_SetCompare2(TIM2, test);
                                pmotor->step_time = 0;
                            }
                        }
                    }
                    else //两段式
                    {
                        pmotor->state = dec; //进入减速阶段
                    }
                    break;
                case avg: //匀速阶段
                    pmotor->avg_step--;
                    if (pmotor->avg_step == 0)
                        pmotor->state = dec;
                    break;
                case dec: //减速阶段
                    if (pmotor->passed_puase < pmotor->step)
                    {
                        if (pmotor->step_time > TIME_PER_DIV * 1000) //一个频率的步数走完
                        {
                            pmotor->f_index--;
                            TIM2->ARR = table_time[pmotor->f_index];
                            test = table_time[pmotor->f_index] >> 1;
                            TIM_SetCompare2(TIM2, test);
                            pmotor->step_time = 0;
                            if (pmotor->f_index == 0)
                                pmotor->f_index = 1; //修正，防止减速阶段结束了，步数没走完
                        }
                    }
                    else
                    {
                        TIM_Cmd(TIM2, DISABLE); //失能TIM2
                    }
                    break;
                }
            }
        }
    }
}

/*********************************END OF FILE**********************************/
